#include "SysTime.h"

#include "Timer.h"
#include "Tools.h"

static SysTime global_sys_time;
static bool    is_inited = false;

static void
sys_time_cb(SysTime *self)
{
        self->seconds += 1;
        if (self->seconds >= 60) {
                self->minutes += 1;
                if (self->minutes >= 60) {
                        self->hours += 1;
                        if (self->hours >= 24)
                                self->hours = 0;
                        self->minutes = 0;
                }
                self->seconds = 0;
        }
}

SysTime *
sys_time_new_from_global(void)
{
        if (is_inited)
                return &global_sys_time;
        timer_init(TIMER(&global_sys_time),
                   OBJECT_IRQ_HANDLER(sys_time_cb),
                   7200,
                   10000);
        global_sys_time.hours   = 0;
        global_sys_time.minutes = 0;
        global_sys_time.seconds = 0;
        //
        is_inited = true;
        return &global_sys_time;
}

void
sys_time_format_to_array(SysTime *self, char *array)
{
        sprintf_b(array,
                  "%2u:%2u:%2u",
                  (unsigned int)self->hours,
                  (unsigned int)self->minutes,
                  (unsigned int)self->seconds);
}

void
sys_time_set_now(SysTime *self, uint8_t hours, uint8_t minutes, uint8_t seconds)
{
        self->seconds = seconds > 59 ? 0 : seconds;
        self->minutes = minutes > 59 ? 0 : minutes;
        self->hours   = hours > 23 ? 0 : hours;
}

void
sys_time_get_now(SysTime *self, SysTimeAtomic *atomic)
{
        atomic->seconds = self->seconds;
        atomic->minutes = self->minutes;
        atomic->hours   = self->hours;
}

static void
sys_time_atomic_add_once(SysTimeAtomic *atomic)
{
        atomic->seconds += 1;
        if (atomic->seconds >= 60) {
                atomic->minutes += 1;
                if (atomic->minutes >= 60) {
                        atomic->hours += 1;
                        if (atomic->hours >= 24)
                                atomic->hours = 0;
                        atomic->minutes = 0;
                }
                atomic->seconds = 0;
        }
}

bool
sys_time_compare_with_atomic(const SysTime *self, const SysTimeAtomic *atomic)
{
        if (self->seconds != atomic->seconds)
                return false;
        if (self->minutes != atomic->minutes)
                return false;
        if (self->hours != atomic->hours)
                return false;
        return true;
}

void
sys_time_atomic_add_seconds(SysTimeAtomic *atomic, uint16_t seconds)
{
        for (uint16_t i = 0; i < seconds; i++)
                sys_time_atomic_add_once(atomic);
}
